package com.coursehub.progress.service.impl;

import com.coursehub.progress.dto.ChapterProgressUpdateDto;
import com.coursehub.progress.dto.MaterialProgressUpdateDto;
import com.coursehub.progress.dto.ProgressResponseDto;
import com.coursehub.progress.entity.*;
import com.coursehub.progress.repository.StudentChapterRepository;
import com.coursehub.progress.repository.StudentMaterialRepository;
import com.coursehub.progress.repository.StudentExerciseRepository;
import com.coursehub.progress.service.ProgressService;
import com.coursehub.shared.dto.ApiResponse;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 学习进度服务实现类
 */
@Service
@Transactional
@RequiredArgsConstructor
public class ProgressServiceImpl implements ProgressService {
    
    private static final Logger log = LoggerFactory.getLogger(ProgressServiceImpl.class);
    
    private final StudentChapterRepository studentChapterRepository;
    private final StudentMaterialRepository studentMaterialRepository;
    private final StudentExerciseRepository studentExerciseRepository;
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    @Value("${coursehub.services.urls.user-management}")
    private String userServiceUrl;
    
    @Value("${coursehub.services.urls.course-management}")
    private String courseServiceUrl;
    
    @Value("${coursehub.services.urls.exercise-management}")
    private String exerciseServiceUrl;
    
    @Override
    public StudentChapter updateChapterProgress(ChapterProgressUpdateDto dto) {
        // 验证章节是否存在
        if (!validateChapter(dto.getChapterId())) {
            throw new IllegalArgumentException("章节不存在: " + dto.getChapterId());
        }
        
        // 验证用户是否存在
        if (!validateUser(dto.getUserId())) {
            throw new IllegalArgumentException("用户不存在: " + dto.getUserId());
        }
        
        StudentChapterId id = new StudentChapterId(dto.getUserId(), dto.getCourseId(), dto.getChapterId());
        StudentChapter studentChapter = studentChapterRepository.findById(id)
                .orElse(new StudentChapter());
        
        studentChapter.setUserId(dto.getUserId());
        studentChapter.setCourseId(dto.getCourseId());
        studentChapter.setChapterId(dto.getChapterId());
        studentChapter.setIsFinished(dto.getIsFinished());
        
        return studentChapterRepository.save(studentChapter);
    }
    
    @Override
    public StudentMaterial updateMaterialProgress(MaterialProgressUpdateDto dto) {
        // 验证资料是否存在
        if (!validateMaterial(dto.getMaterialId())) {
            throw new IllegalArgumentException("资料不存在: " + dto.getMaterialId());
        }
        
        // 验证用户是否存在
        if (!validateUser(dto.getUserId())) {
            throw new IllegalArgumentException("用户不存在: " + dto.getUserId());
        }
        
        StudentMaterialId id = new StudentMaterialId(dto.getUserId(), dto.getCourseId(), dto.getChapterId(), dto.getMaterialId());
        StudentMaterial studentMaterial = studentMaterialRepository.findById(id)
                .orElse(new StudentMaterial());
        
        studentMaterial.setUserId(dto.getUserId());
        studentMaterial.setCourseId(dto.getCourseId());
        studentMaterial.setChapterId(dto.getChapterId());
        studentMaterial.setMaterialId(dto.getMaterialId());
        studentMaterial.setIsFinished(dto.getIsFinished());
        
        return studentMaterialRepository.save(studentMaterial);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<StudentChapter> getUserChapterProgress(String userId, String courseId) {
        // 验证用户和课程是否存在
        if (!validateUser(userId)) {
            throw new IllegalArgumentException("用户不存在: " + userId);
        }
        if (!validateCourse(courseId)) {
            throw new IllegalArgumentException("课程不存在: " + courseId);
        }
        
        // 通过课程服务获取课程的所有章节ID
        List<String> chapterIds = getChapterIdsByCourse(courseId);
        
        // 获取用户在这些章节的学习进度
        List<StudentChapter> allProgress = studentChapterRepository.findByUserId(userId);
        
        return allProgress.stream()
                .filter(progress -> chapterIds.contains(progress.getChapterId()))
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<StudentMaterial> getUserMaterialProgress(String userId, String courseId) {
        // 验证用户和课程是否存在
        if (!validateUser(userId)) {
            throw new IllegalArgumentException("用户不存在: " + userId);
        }
        if (!validateCourse(courseId)) {
            throw new IllegalArgumentException("课程不存在: " + courseId);
        }
        
        // 通过课程服务获取课程的所有资料ID
        List<String> materialIds = getMaterialIdsByCourse(courseId);
        
        // 获取用户在这些资料的学习进度
        List<StudentMaterial> allProgress = studentMaterialRepository.findByUserId(userId);
        
        return allProgress.stream()
                .filter(progress -> materialIds.contains(progress.getMaterialId()))
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional(readOnly = true)
    public ProgressResponseDto getUserOverallProgress(String userId, String courseId) {
        ProgressResponseDto response = new ProgressResponseDto();
        response.setUserId(userId);
        response.setCourseId(courseId);
        
        // 获取章节进度
        List<StudentChapter> chapterProgress = getUserChapterProgress(userId, courseId);
        Map<String, Integer> chapterProgressMap = new HashMap<>();
        List<String> completedChapters = new ArrayList<>();
        
        for (StudentChapter progress : chapterProgress) {
            int progressPercent = progress.getIsFinished() ? 100 : 0;
            chapterProgressMap.put(progress.getChapterId(), progressPercent);
            if (progress.getIsFinished()) {
                completedChapters.add(progress.getChapterId());
            }
        }
        
        // 获取资料进度
        List<StudentMaterial> materialProgress = getUserMaterialProgress(userId, courseId);
        Map<String, Boolean> materialProgressMap = new HashMap<>();
        List<String> completedMaterials = new ArrayList<>();
        
        for (StudentMaterial progress : materialProgress) {
            materialProgressMap.put(progress.getMaterialId(), progress.getIsFinished());
            if (progress.getIsFinished()) {
                completedMaterials.add(progress.getMaterialId());
            }
        }
        
        // 计算整体进度
        Integer overallProgress = getCourseProgress(userId, courseId);
        
        response.setOverallProgress(overallProgress);
        response.setChapterProgress(chapterProgressMap);
        response.setMaterialProgress(materialProgressMap);
        response.setCompletedChapters(completedChapters);
        response.setCompletedMaterials(completedMaterials);
        
        return response;
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getCourseProgress(String userId, String courseId) {
        // 获取课程的所有章节
        List<String> chapterIds = getChapterIdsByCourse(courseId);
        
        if (chapterIds.isEmpty()) {
            return 100; // 没有章节视为已完成
        }
        
        // 统计已完成的章节数量
        List<StudentChapter> userProgress = studentChapterRepository.findByUserId(userId);
        long completedCount = userProgress.stream()
                .filter(progress -> chapterIds.contains(progress.getChapterId()))
                .filter(StudentChapter::getIsFinished)
                .count();
        
        return (int) ((completedCount * 100) / chapterIds.size());
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getChapterProgress(String userId, String chapterId) {
        // 获取章节下的所有资料
        List<String> materialIds = getMaterialIdsByChapter(chapterId);
        
        if (materialIds.isEmpty()) {
            // 章节无资料时，直接通过 StudentChapter 表判断章节是否完成
            return studentChapterRepository.findByUserIdAndChapterId(userId, chapterId)
                    .filter(StudentChapter::getIsFinished)
                    .map(s -> 100)
                    .orElse(0);
        }
        
        // 统计已完成的资料数量
        List<StudentMaterial> userProgress = studentMaterialRepository.findByUserId(userId);
        long completedCount = userProgress.stream()
                .filter(progress -> materialIds.contains(progress.getMaterialId()))
                .filter(StudentMaterial::getIsFinished)
                .count();
        
        return (int) ((completedCount * 100) / materialIds.size());
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getMaterialProgress(String userId, String materialId) {
        return studentMaterialRepository.findByUserIdAndMaterialId(userId, materialId)
                .map(sm -> sm.getIsFinished() ? 100 : 0)
                .orElse(0);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Map<String, Integer> getBatchChapterProgress(String userId, List<String> chapterIds) {
        Map<String, Integer> progressMap = new HashMap<>();
        
        for (String chapterId : chapterIds) {
            progressMap.put(chapterId, getChapterProgress(userId, chapterId));
        }
        
        return progressMap;
    }
    
    @Override
    @Transactional(readOnly = true)
    public Map<String, Boolean> getBatchMaterialProgress(String userId, List<String> materialIds) {
        List<StudentMaterial> userProgress = studentMaterialRepository.findByUserId(userId);
        Map<String, Boolean> progressMap = new HashMap<>();
        
        for (String materialId : materialIds) {
            boolean isCompleted = userProgress.stream()
                    .anyMatch(progress -> progress.getMaterialId().equals(materialId) && progress.getIsFinished());
            progressMap.put(materialId, isCompleted);
        }
        
        return progressMap;
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getClassCompletionRate(String classId) {
        // 通过课程服务获取班级信息和学生列表
        // 这里需要调用课程服务的API
        try {
            // 获取班级对应的课程ID
            String courseId = getCourseIdByClassId(classId);
            
            // 获取课程总章节数
            List<String> chapterIds = getChapterIdsByCourse(courseId);
            int totalChapters = chapterIds.size();
            
            if (totalChapters == 0) {
                return 100; // 课程没有章节
            }
            
            // 获取班级所有学生
            List<String> studentIds = getStudentIdsByClassId(classId);
            
            if (studentIds.isEmpty()) {
                return 0; // 班级没有学生
            }
            
            // 计算所有学生的完成章节总数
            int totalFinishedChapters = 0;
            for (String studentId : studentIds) {
                List<StudentChapter> studentProgress = studentChapterRepository.findByUserId(studentId);
                long finishedCount = studentProgress.stream()
                        .filter(progress -> chapterIds.contains(progress.getChapterId()))
                        .filter(StudentChapter::getIsFinished)
                        .count();
                totalFinishedChapters += finishedCount;
            }
            
            // 计算班级完成比例
            int totalStudents = studentIds.size();
            return (int) ((totalFinishedChapters * 100) / (totalChapters * totalStudents));
            
        } catch (Exception e) {
            log.error("计算班级完成率失败: {}", e.getMessage());
            throw new RuntimeException("计算班级完成率失败", e);
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getExerciseCompletionRate(String exerciseId) {
        // 通过练习服务获取练习信息和提交统计
        try {
            String url = exerciseServiceUrl + "/api/exercises/" + exerciseId + "/completion-rate";
            Map<String, Object> response = restTemplate.getForObject(url, Map.class);
            return (Integer) response.get("completionRate");
        } catch (Exception e) {
            log.error("获取练习完成率失败: {}", e.getMessage());
            throw new RuntimeException("获取练习完成率失败", e);
        }
    }
    
    @Override
    public boolean validateUser(String userId) {
        try {
            String url = userServiceUrl + "/api/users/" + userId + "/exists";
            String response = restTemplate.getForObject(url, String.class);
            
            // 解析ApiResponse<Boolean>格式的响应
            ApiResponse<Boolean> apiResponse = objectMapper.readValue(response, 
                new TypeReference<ApiResponse<Boolean>>() {});
            
            if (apiResponse.getCode() == 200 && apiResponse.getData() != null) {
                return apiResponse.getData();
            }
            
            log.warn("用户验证响应异常: code={}, message={}", apiResponse.getCode(), apiResponse.getMessage());
            return false;
        } catch (Exception e) {
            log.warn("验证用户失败: {}", e.getMessage());
            return false;
        }
    }
    
    @Override
    public boolean validateCourse(String courseId) {
        try {
            String url = courseServiceUrl + "/api/courses/" + courseId + "/exists";
            ResponseEntity<ApiResponse> response = restTemplate.getForEntity(url, ApiResponse.class);
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                ApiResponse apiResponse = response.getBody();
                if (apiResponse.getCode() == 200 && apiResponse.getData() != null) {
                    return Boolean.TRUE.equals(apiResponse.getData());
                }
            }
            return false;
        } catch (Exception e) {
            log.warn("验证课程失败: {}", e.getMessage());
            return false;
        }
    }
    
    @Override
    public boolean validateChapter(String chapterId) {
        try {
            String url = courseServiceUrl + "/api/chapters/" + chapterId + "/exists";
            Boolean exists = restTemplate.getForObject(url, Boolean.class);
            return Boolean.TRUE.equals(exists);
        } catch (Exception e) {
            log.warn("验证章节失败: {}", e.getMessage());
            return false;
        }
    }
    
    @Override
    public boolean validateMaterial(String materialId) {
        try {
            String url = courseServiceUrl + "/api/materials/" + materialId + "/exists";
            Boolean exists = restTemplate.getForObject(url, Boolean.class);
            return Boolean.TRUE.equals(exists);
        } catch (Exception e) {
            log.warn("验证资料失败: {}", e.getMessage());
            return false;
        }
    }
    
    @Override
    public boolean validateClass(String classId) {
        try {
            String url = courseServiceUrl + "/api/classes/" + classId + "/exists";
            Boolean exists = restTemplate.getForObject(url, Boolean.class);
            return Boolean.TRUE.equals(exists);
        } catch (Exception e) {
            log.warn("验证班级失败: {}", e.getMessage());
            return false;
        }
    }
    
    @Override
    public boolean validateExercise(String exerciseId) {
        try {
            String url = exerciseServiceUrl + "/api/exercises/" + exerciseId + "/exists";
            Boolean exists = restTemplate.getForObject(url, Boolean.class);
            return Boolean.TRUE.equals(exists);
        } catch (Exception e) {
            log.warn("验证练习失败: {}", e.getMessage());
            return false;
        }
    }
    
    // 私有辅助方法
    
    private List<String> getChapterIdsByCourse(String courseId) {
        try {
            String url = courseServiceUrl + "/api/chapters/course/" + courseId;
            String[] chapterIds = restTemplate.getForObject(url, String[].class);
            return chapterIds != null ? Arrays.asList(chapterIds) : Collections.emptyList();
        } catch (Exception e) {
            log.error("获取课程章节失败: {}", e.getMessage());
            return Collections.emptyList();
        }
    }
    
    private List<String> getMaterialIdsByCourse(String courseId) {
        try {
            String url = courseServiceUrl + "/api/materials/course/" + courseId;
            String[] materialIds = restTemplate.getForObject(url, String[].class);
            return materialIds != null ? Arrays.asList(materialIds) : Collections.emptyList();
        } catch (Exception e) {
            log.error("获取课程资料失败: {}", e.getMessage());
            return Collections.emptyList();
        }
    }
    
    private List<String> getMaterialIdsByChapter(String chapterId) {
        try {
            String url = courseServiceUrl + "/api/materials/chapter/" + chapterId;
            String[] materialIds = restTemplate.getForObject(url, String[].class);
            return materialIds != null ? Arrays.asList(materialIds) : Collections.emptyList();
        } catch (Exception e) {
            log.error("获取章节资料失败: {}", e.getMessage());
            return Collections.emptyList();
        }
    }
    
    private String getCourseIdByClassId(String classId) {
        try {
            String url = courseServiceUrl + "/api/classes/" + classId + "/course";
            return restTemplate.getForObject(url, String.class);
        } catch (Exception e) {
            log.error("获取班级课程失败: {}", e.getMessage());
            throw new RuntimeException("获取班级课程失败", e);
        }
    }
    
    private List<String> getStudentIdsByClassId(String classId) {
        try {
            String url = courseServiceUrl + "/api/classes/" + classId + "/students";
            String[] studentIds = restTemplate.getForObject(url, String[].class);
            return studentIds != null ? Arrays.asList(studentIds) : Collections.emptyList();
        } catch (Exception e) {
            log.error("获取班级学生失败: {}", e.getMessage());
            return Collections.emptyList();
        }
    }
    
    // ====================== 资料学习状态管理方法实现（兼容单体系统） ======================
    
    @Override
    @Transactional(readOnly = true)
    public List<Map<String, Object>> getCompletedMaterialsByStudentAndChapter(String userId, String chapterId) {
        log.info("获取学生在章节中已完成的资料: userId={}, chapterId={}", userId, chapterId);
        
        // 验证用户和章节是否存在
        if (!validateUser(userId)) {
            throw new IllegalArgumentException("用户不存在: " + userId);
        }
        if (!validateChapter(chapterId)) {
            throw new IllegalArgumentException("章节不存在: " + chapterId);
        }
        
        // 获取章节下的所有资料ID
        List<String> materialIds = getMaterialIdsByChapter(chapterId);
        
        // 获取学生已完成的资料
        List<Map<String, Object>> completedMaterials = new ArrayList<>();
        for (String materialId : materialIds) {
            Optional<StudentMaterial> studentMaterial = studentMaterialRepository
                    .findByUserIdAndMaterialId(userId, materialId);
            
            if (studentMaterial.isPresent() && studentMaterial.get().getIsFinished()) {
                Map<String, Object> materialInfo = new HashMap<>();
                materialInfo.put("materialId", materialId);
                materialInfo.put("isFinished", true);
                materialInfo.put("finishedAt", studentMaterial.get().getUpdatedAt());
                completedMaterials.add(materialInfo);
            }
        }
        
        log.info("找到{}个已完成资料", completedMaterials.size());
        return completedMaterials;
    }
    
    @Override
    @Transactional
    public void updateStudentMaterialStatus(String userId, String materialId, boolean isFinished) {
        log.info("更新学生资料学习状态: userId={}, materialId={}, isFinished={}", userId, materialId, isFinished);
        
        // 验证用户和资料是否存在
        if (!validateUser(userId)) {
            throw new IllegalArgumentException("用户不存在: " + userId);
        }
        if (!validateMaterial(materialId)) {
            throw new IllegalArgumentException("资料不存在: " + materialId);
        }
        
        // 查找或创建学生资料记录
        Optional<StudentMaterial> existingRecord = studentMaterialRepository
                .findByUserIdAndMaterialId(userId, materialId);
        
        StudentMaterial studentMaterial;
        if (existingRecord.isPresent()) {
            studentMaterial = existingRecord.get();
            studentMaterial.setIsFinished(isFinished);
            studentMaterial.setUpdatedAt(LocalDateTime.now());
        } else {
            // 创建新记录
            StudentMaterialId id = new StudentMaterialId();
            id.setUserId(userId);
            id.setMaterialId(materialId);
            
            studentMaterial = new StudentMaterial();
            studentMaterial.setUserId(userId);
            studentMaterial.setMaterialId(materialId);
            studentMaterial.setIsFinished(isFinished);
            studentMaterial.setCreatedAt(LocalDateTime.now());
            studentMaterial.setUpdatedAt(LocalDateTime.now());
        }
        
        studentMaterialRepository.save(studentMaterial);
        log.info("学生资料学习状态更新成功");
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean getStudentMaterialStatus(String userId, String materialId) {
        log.info("获取学生资料学习状态: userId={}, materialId={}", userId, materialId);
        
        // 验证用户和资料是否存在
        if (!validateUser(userId)) {
            throw new IllegalArgumentException("用户不存在: " + userId);
        }
        if (!validateMaterial(materialId)) {
            throw new IllegalArgumentException("资料不存在: " + materialId);
        }
        
        Optional<StudentMaterial> studentMaterial = studentMaterialRepository
                .findByUserIdAndMaterialId(userId, materialId);
        
        boolean isFinished = studentMaterial.map(StudentMaterial::getIsFinished).orElse(false);
        log.info("学生资料学习状态: {}", isFinished);
        return isFinished;
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getCompletedChapterIds(String userId, String courseId) {
        log.info("获取学生已完成章节ID列表: userId={}, courseId={}", userId, courseId);
        
        List<String> chapterIds = getChapterIdsByCourse(courseId);
        if (chapterIds.isEmpty()) {
            return Collections.emptyList();
        }
        
        return studentChapterRepository.findByUserIdAndChapterIdInAndIsFinishedTrue(userId, chapterIds)
                .stream()
                .map(StudentChapter::getChapterId)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getCompletedMaterialIds(String userId, String courseId) {
        log.info("获取学生已完成资料ID列表: userId={}, courseId={}", userId, courseId);
        
        List<String> materialIds = getMaterialIdsByCourse(courseId);
        if (materialIds.isEmpty()) {
            return Collections.emptyList();
        }
        
        return studentMaterialRepository.findByUserIdAndMaterialIdInAndIsFinishedTrue(userId, materialIds)
                .stream()
                .map(StudentMaterial::getMaterialId)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional
    public void markChapterAsComplete(String userId, String chapterId) {
        log.info("标记章节完成: userId={}, chapterId={}", userId, chapterId);
        
        Optional<StudentChapter> existingProgress = studentChapterRepository
                .findByUserIdAndChapterId(userId, chapterId);
        
        if (existingProgress.isPresent()) {
            StudentChapter progress = existingProgress.get();
            progress.setIsFinished(true);
            progress.setFinishedAt(LocalDateTime.now());
            studentChapterRepository.save(progress);
        } else {
            StudentChapter newProgress = new StudentChapter();
            newProgress.setUserId(userId);
            newProgress.setChapterId(chapterId);
            newProgress.setIsFinished(true);
            newProgress.setFinishedAt(LocalDateTime.now());
            studentChapterRepository.save(newProgress);
        }
        
        log.info("章节标记完成成功: userId={}, chapterId={}", userId, chapterId);
    }
    
    @Override
    @Transactional
    public void markMaterialAsComplete(String userId, String materialId) {
        log.info("标记资料完成: userId={}, materialId={}", userId, materialId);
        
        Optional<StudentMaterial> existingProgress = studentMaterialRepository
                .findByUserIdAndMaterialId(userId, materialId);
        
        if (existingProgress.isPresent()) {
            StudentMaterial progress = existingProgress.get();
            progress.setIsFinished(true);
            progress.setFinishedAt(LocalDateTime.now());
            studentMaterialRepository.save(progress);
        } else {
            StudentMaterial newProgress = new StudentMaterial();
            newProgress.setUserId(userId);
            newProgress.setMaterialId(materialId);
            newProgress.setIsFinished(true);
            newProgress.setFinishedAt(LocalDateTime.now());
            studentMaterialRepository.save(newProgress);
        }
        
        log.info("标记资料为已完成: userId={}, materialId={}", userId, materialId);
    }
    
    // ==================== 练习完成状态管理实现 ====================
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getCompletedExerciseIds(String userId) {
        log.info("获取用户已完成的练习列表: userId={}", userId);
        
        List<StudentExercise> completedExercises = studentExerciseRepository.findByUserIdAndIsFinishedTrue(userId);
        return completedExercises.stream()
                .map(StudentExercise::getExerciseId)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getUnfinishedExerciseIds(String userId) {
        log.info("获取用户未完成的练习列表: userId={}", userId);
        
        List<StudentExercise> unfinishedExercises = studentExerciseRepository.findByUserIdAndIsFinishedFalse(userId);
        return unfinishedExercises.stream()
                .map(StudentExercise::getExerciseId)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getCompletedExerciseIdsByCourse(String userId, String courseId) {
        log.info("根据课程ID获取用户已完成的练习: userId={}, courseId={}", userId, courseId);
        
        try {
            // 通过微服务调用获取课程相关的练习ID列表
            String url = exerciseServiceUrl + "/api/exercises/course/" + courseId + "/all";
            ResponseEntity<List> response = restTemplate.getForEntity(url, List.class);
            
            if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null) {
                log.warn("获取课程练习列表失败，返回空列表");
                return new ArrayList<>();
            }
            
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> exercises = response.getBody();
            List<String> exerciseIds = exercises.stream()
                    .map(exercise -> (String) exercise.get("exerciseId"))
                    .collect(Collectors.toList());
            
            if (exerciseIds.isEmpty()) {
                log.info("课程 {} 没有练习，返回空列表", courseId);
                return new ArrayList<>();
            }
            
            // 获取用户在这些练习中的完成状态
            List<String> completedExerciseIds = new ArrayList<>();
            for (String exerciseId : exerciseIds) {
                if (isExerciseCompleted(userId, exerciseId)) {
                    completedExerciseIds.add(exerciseId);
                }
            }
            
            log.info("用户 {} 在课程 {} 中已完成 {} 个练习", userId, courseId, completedExerciseIds.size());
            return completedExerciseIds;
            
        } catch (Exception e) {
            log.error("获取用户课程已完成练习失败: userId={}, courseId={}, 错误: {}", userId, courseId, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getUnfinishedExerciseIdsByCourse(String userId, String courseId) {
        log.info("根据课程ID获取用户未完成的练习: userId={}, courseId={}", userId, courseId);
        
        try {
            // 通过微服务调用获取课程相关的练习ID列表
            String url = exerciseServiceUrl + "/api/exercises/course/" + courseId + "/all";
            ResponseEntity<List> response = restTemplate.getForEntity(url, List.class);
            
            if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null) {
                log.warn("获取课程练习列表失败，返回空列表");
                return new ArrayList<>();
            }
            
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> exercises = response.getBody();
            List<String> exerciseIds = exercises.stream()
                    .map(exercise -> (String) exercise.get("exerciseId"))
                    .collect(Collectors.toList());
            
            if (exerciseIds.isEmpty()) {
                log.info("课程 {} 没有练习，返回空列表", courseId);
                return new ArrayList<>();
            }
            
            // 获取用户在这些练习中的未完成状态
            List<String> unfinishedExerciseIds = new ArrayList<>();
            for (String exerciseId : exerciseIds) {
                if (!isExerciseCompleted(userId, exerciseId)) {
                    unfinishedExerciseIds.add(exerciseId);
                }
            }
            
            log.info("用户 {} 在课程 {} 中未完成 {} 个练习", userId, courseId, unfinishedExerciseIds.size());
            return unfinishedExerciseIds;
            
        } catch (Exception e) {
            log.error("获取用户课程未完成练习失败: userId={}, courseId={}, 错误: {}", userId, courseId, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    @Override
    @Transactional
    public void markExerciseAsComplete(String userId, String exerciseId, Integer score) {
        log.info("标记练习为已完成: userId={}, exerciseId={}, score={}", userId, exerciseId, score);
        
        // 验证用户和练习是否存在
        if (!validateUser(userId)) {
            throw new IllegalArgumentException("用户不存在: " + userId);
        }
        if (!validateExercise(exerciseId)) {
            throw new IllegalArgumentException("练习不存在: " + exerciseId);
        }
        
        Optional<StudentExercise> existingRecord = studentExerciseRepository.findByUserIdAndExerciseId(userId, exerciseId);
        
        if (existingRecord.isPresent()) {
            // 更新现有记录
            StudentExercise studentExercise = existingRecord.get();
            studentExercise.setIsFinished(true);
            studentExercise.setScore(score);
            studentExercise.setFinishedAt(LocalDateTime.now());
            studentExerciseRepository.save(studentExercise);
        } else {
            // 创建新记录
            StudentExercise studentExercise = new StudentExercise();
            studentExercise.setUserId(userId);
            studentExercise.setExerciseId(exerciseId);
            studentExercise.setIsFinished(true);
            studentExercise.setScore(score);
            studentExercise.setFinishedAt(LocalDateTime.now());
            studentExerciseRepository.save(studentExercise);
        }
        
        log.info("练习标记为已完成成功: userId={}, exerciseId={}", userId, exerciseId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean isExerciseCompleted(String userId, String exerciseId) {
        return studentExerciseRepository.existsByUserIdAndExerciseIdAndIsFinishedTrue(userId, exerciseId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean getStudentExerciseStatus(String userId, String exerciseId) {
        Optional<StudentExercise> record = studentExerciseRepository.findByUserIdAndExerciseId(userId, exerciseId);
        return record.map(StudentExercise::getIsFinished).orElse(false);
    }
    
    @Override
    @Transactional
    public void updateStudentExerciseStatus(String userId, String exerciseId, boolean isFinished, Integer score) {
        log.info("更新学生练习状态: userId={}, exerciseId={}, isFinished={}, score={}", userId, exerciseId, isFinished, score);
        
        // 验证用户和练习是否存在
        if (!validateUser(userId)) {
            throw new IllegalArgumentException("用户不存在: " + userId);
        }
        if (!validateExercise(exerciseId)) {
            throw new IllegalArgumentException("练习不存在: " + exerciseId);
        }
        
        Optional<StudentExercise> existingRecord = studentExerciseRepository.findByUserIdAndExerciseId(userId, exerciseId);
        
        if (existingRecord.isPresent()) {
            // 更新现有记录
            StudentExercise studentExercise = existingRecord.get();
            studentExercise.setIsFinished(isFinished);
            studentExercise.setScore(score);
            if (isFinished) {
                studentExercise.setFinishedAt(LocalDateTime.now());
            }
            studentExerciseRepository.save(studentExercise);
        } else {
            // 创建新记录
            StudentExercise studentExercise = new StudentExercise();
            studentExercise.setUserId(userId);
            studentExercise.setExerciseId(exerciseId);
            studentExercise.setIsFinished(isFinished);
            studentExercise.setScore(score);
            if (isFinished) {
                studentExercise.setFinishedAt(LocalDateTime.now());
            }
            studentExerciseRepository.save(studentExercise);
        }
        
        log.info("学生练习状态更新成功: userId={}, exerciseId={}", userId, exerciseId);
    }
}